package com.xof.phonecall.telecom

import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.telecom.*
import android.widget.Toast
import androidx.annotation.RequiresApi
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.xof.phonecall.MyApplication
import com.xof.phonecall.telecom.test.TestCallActivity


class MyConnectionService : ConnectionService() {

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        println("MyConnectionService: onStartCommand")
        return super.onStartCommand(intent, flags, startId)
    }

    @RequiresApi(Build.VERSION_CODES.P)
    override fun onCreateOutgoingConnection(
        connectionManagerPhoneAccount: PhoneAccountHandle?,
        request: ConnectionRequest?
    ): Connection {
        println("MyConnectionService: onCreateOutgoingConnection")
//        return super.onCreateOutgoingConnection(connectionManagerPhoneAccount, request)

        val handle: Uri? = request?.getAddress()
        val number: String? = request?.getAddress()?.getSchemeSpecificPart()
        println("call, number: $number")
        // Crash on 555-DEAD to test call service crashing.
        // Crash on 555-DEAD to test call service crashing.
        if ("5550340" == number) {
            throw RuntimeException("Goodbye, cruel world.")
        }
        val extras: Bundle? = request?.getExtras()
        val gatewayPackage = extras?.getString(TelecomManager.GATEWAY_PROVIDER_PACKAGE)
        val originalHandle = extras?.getParcelable<Uri>(TelecomManager.GATEWAY_ORIGINAL_ADDRESS)
        if (extras?.containsKey(TelecomManager.EXTRA_CALL_SUBJECT) == true) {
            val callSubject = extras.getString(TelecomManager.EXTRA_CALL_SUBJECT)
            println("Got subject: $callSubject")
            Toast.makeText(
                applicationContext, "Got subject :$callSubject",
                Toast.LENGTH_SHORT
            ).show()
        }
        println(
            "gateway package [" + gatewayPackage + "], original handle [" +
                    originalHandle + "]"
        )
        val connection = MyTestConnection(false /* isIncoming */, request!!)
        connection.setCallerDisplayName("Telecom", TelecomManager.PRESENTATION_ALLOWED)
        connection.audioModeIsVoip = true
        connection.setAddress(handle!!, TelecomManager.PRESENTATION_ALLOWED)

        // If the number starts with 555, then we handle it ourselves. If not, then we
        // use a remote connection service.
        // TODO: Have a special phone number to test the account-picker dialog flow.
        // If the number starts with 555, then we handle it ourselves. If not, then we
        // use a remote connection service.
        // TODO: Have a special phone number to test the account-picker dialog flow.
        if (number != null && number.startsWith("555")) {
            // Normally we would use the original request as is, but for testing purposes, we are
            // adding ".." to the end of the number to follow its path more easily through the logs.
            val request = ConnectionRequest(
                request.getAccountHandle(),
                Uri.fromParts(
                    handle.scheme,
                    handle.schemeSpecificPart + "..", ""
                ),
                request.getExtras(),
                request.getVideoState()
            )
            connection.startOutgoing()
            for (c: Connection in allConnections) {
                c.setOnHold()
            }
        } else {
            println("Not a test number")
        }
        return connection
    }

    override fun onCreateOutgoingConnectionFailed(
        connectionManagerPhoneAccount: PhoneAccountHandle?,
        request: ConnectionRequest?
    ) {
        super.onCreateOutgoingConnectionFailed(connectionManagerPhoneAccount, request)
    }

    override fun onCreateIncomingConnection(
        connectionManagerPhoneAccount: PhoneAccountHandle?,
        request: ConnectionRequest?
    ): Connection {
        super.onCreateIncomingConnection(connectionManagerPhoneAccount, request)

        val conn = MyConnection()
        conn.connectionProperties = Connection.PROPERTY_SELF_MANAGED
        conn.setCallerDisplayName("Telecom", TelecomManager.PRESENTATION_ALLOWED)
        conn.setAddress(Uri.parse("tel:" + "10086"), TelecomManager.PRESENTATION_ALLOWED)
        conn.setRinging()
        conn.setInitializing()
        conn.setActive()
        return conn
    }

    override fun onCreateIncomingConnectionFailed(
        connectionManagerPhoneAccount: PhoneAccountHandle?,
        request: ConnectionRequest?
    ) {

    }


    private fun activateCall(connection: MyTestConnection) {

    }

    private fun destroyCall(connection: MyTestConnection) {

    }

    private fun setAddress(connection: Connection, address: Uri) {
        connection.setAddress(address, TelecomManager.PRESENTATION_ALLOWED)
        if ("5551234" == address.schemeSpecificPart) {
            connection.setCallerDisplayName("Hello World", TelecomManager.PRESENTATION_ALLOWED)
        }
    }

    @RequiresApi(Build.VERSION_CODES.P)
    class MyTestConnection(var isIncoming: Boolean, var request: ConnectionRequest) : Connection() {
        val BUSY_SUFFIX = "2879"

        private var mIsIncoming = false
        private val mHandler = Handler(Looper.getMainLooper())

        private var mOriginalRequest: ConnectionRequest? = null

        private val mHangupReceiver: BroadcastReceiver = object : BroadcastReceiver() {
            override fun onReceive(context: Context, intent: Intent) {
                setDisconnected(DisconnectCause(DisconnectCause.MISSED))
                destroy()
            }
        }

        init {
            mIsIncoming = isIncoming
            mOriginalRequest = request
            // Assume all calls are video capable.
            var capabilities = connectionCapabilities
            capabilities = capabilities or CAPABILITY_SUPPORTS_VT_LOCAL_BIDIRECTIONAL
            capabilities = capabilities or CAPABILITY_SUPPORTS_VT_REMOTE_BIDIRECTIONAL
            capabilities = capabilities or CAPABILITY_CAN_UPGRADE_TO_VIDEO
            capabilities = capabilities or CAPABILITY_MUTE
            capabilities = capabilities or CAPABILITY_SUPPORT_HOLD
            capabilities = capabilities or CAPABILITY_HOLD
            capabilities = capabilities or CAPABILITY_RESPOND_VIA_TEXT
            connectionCapabilities = capabilities
            var properties = connectionProperties
            if (mOriginalRequest!!.isRequestingRtt()) {
                properties = properties or PROPERTY_IS_RTT
            }
            properties = properties or PROPERTY_SELF_MANAGED
            connectionProperties = properties
            if (isIncoming) {
                val newExtras = if (extras == null) Bundle() else extras
                newExtras.putBoolean(EXTRA_ANSWERING_DROPS_FG_CALL, true)
                putExtras(newExtras)
            }
            LocalBroadcastManager.getInstance(MyApplication.context).registerReceiver(
                mHangupReceiver, IntentFilter(TestCallActivity.ACTION_HANGUP_CALLS)
            )
        }

        fun startOutgoing() {
            setDialing()
            setActive()

//            mHandler.postDelayed({
//                if (address.schemeSpecificPart.endsWith(BUSY_SUFFIX)) {
//                    setDisconnected(
//                        DisconnectCause(
//                            DisconnectCause.REMOTE, "Line busy",
//                            "Line busy", "Line busy", ToneGenerator.TONE_SUP_BUSY
//                        )
//                    )
//                    destroy()
//                } else {
//                    setActive()
//                }
//            }, 4000)
            if (mOriginalRequest!!.isRequestingRtt) {
                println("Is RTT call. Starting chatbot service.")
                //                mRttChatbot = new RttChatbot(getApplicationContext(),
//                        mOriginalRequest.getRttTextStream());
//                mRttChatbot.start();
            }
        }

        override fun onDisconnect() {
            setDisconnected(DisconnectCause(DisconnectCause.REMOTE))
            destroy()
        }

        override fun onHold() {
            setOnHold()
        }

        override fun onReject() {
            setDisconnected(DisconnectCause(DisconnectCause.REJECTED))
            destroy()
        }

        override fun onUnhold() {
            setActive()
        }
    }

//    private fun makeConnection(request: ConnectionRequest, incoming: Boolean): Connection? {
//        val remote = if (incoming) createRemoteIncomingConnection(
//            request.accountHandle,
//            request
//        ) else createRemoteOutgoingConnection(request.accountHandle, request)
//        val local = TestManagedConnection(remote, false)
//        mManagedConnectionByRemote.put(remote, local)
//        return local
//    }

//    private fun createCallConnection(phoneNumber: Uri): MyTestConnection? {
//        val conn = MyTestConnection(MyApplication.context)
//        //      信息携带，可以在conn中获取到。
//        val extras = Bundle()
//        conn.setAddress(phoneNumber, PRESENTATION_ALLOWED)
//        conn.setExtras(extras)
//        //      简单的通话功能，hold能力一般不需要进行支持,
////      测试加上hold能力时，新加入的系统来电接通时，会提示正在通话中，请不要挂机。
////      conn.setConnectionCapabilities(Connection.CAPABILITY_HOLD | Connection.CAPABILITY_SUPPORT_HOLD);
//        //设置这个属性才会调用Connection的onShowIncomingCallUi方法
//        conn.connectionProperties = Connection.PROPERTY_SELF_MANAGED
//        conn.audioModeIsVoip = true
//        //        conn.setRingbackRequested(true);
//        //conn相关状态
////        conn.setInitializing();
////        conn.setInitialized();
////        conn.setRinging();//响铃
////        conn.setDialing();//拨号
////        conn.setActive();//接通
////        conn.setDisconnected();//注意，通话结束时必须通过这个方法断开连接
////        conn.destroy();
//        return conn
//    }
}